%module XInput
%include typemaps.i

%{
#include <X11/Xlib.h>
#include <X11/X.h>
#include <X11/extensions/XInput.h>
#include <X11/extensions/XI.h>

typedef struct {
	int event_type;
	XEventClass event_class;
}  EventFinder;


#define MyGetEventClassType(event_t) \
EventFinder*\
My##event_t(XDevice* device) { \
	EventFinder* result = malloc( sizeof(EventFinder) ); \
	event_t(device, result->event_type, result->event_class); \
	return result; \
}

MyGetEventClassType(ProximityIn)
MyGetEventClassType(ProximityOut)
MyGetEventClassType(DeviceMotionNotify)


int
myXSelectExtensionEvent(Display * display, Window w, XEventClass* event_class_list, int count)
{
	int i;
	XEventClass * p = event_class_list;
	printf("---\n");
	for(i=0;i<count;++i) {
		printf("%d ", event_class_list[i], *(p++));
	}
	printf("\n");
	XSelectExtensionEvent(display, w, event_class_list, count);
}

XEvent*
newXEvent()
{
	return malloc(sizeof(XEvent));
}


%}

//%include <X11/extensions/XI.h>

#define IsXExtensionDevice	2


typedef int XID;
typedef XID Window;
typedef	unsigned long	XEventClass;

typedef struct _XDeviceInfo *XDeviceInfoPtr;

typedef struct _XDeviceInfo
    {	
    XID                 id;        
    Atom                type;
    char                *name;
    int                 num_classes;
    int                 use;
    XAnyClassPtr 	inputclassinfo;

    } XDeviceInfo;

typedef struct {
        unsigned char   input_class;
        unsigned char   event_type_base;
} XInputClassInfo;

typedef struct {
        XID                    device_id;
        int                    num_classes;
        XInputClassInfo        *classes;
} XDevice;

typedef struct {
	XEventClass event_class;
	int event_type;
} EventFinder ;


typedef struct {
	int type;
} XEvent;

Display*
XOpenDisplay(const char* host);

Window
DefaultRootWindow(Display* display);

/*
%typemap(java,in) int * OUTPUT {
}
%typemap(java,argout) int * OUTPUT {
	jarg1=*arg1;
}
*/


%typemap(java,jni) XDeviceInfo* {jlongArray} 
%typemap(java,jtype) XDeviceInfo* {long[]} 
%typemap(java,out) XDeviceInfo* {
	jclass strClass;
	jsize size=0;
	int j=0;
	XDeviceInfo* p;
	jlong * jlp;

	size=*arg1;
    	$target = JCALL(NewLongArray, jenv) size);
    	p = $source;
	jlp = JCALL(GetLongArrayElements, jenv) $target, 0);
    	for(j=0; j<size;++j) {
		jlp[j]=(jlong)(int)p;
		++p;
    	}
	JCALL(ReleaseLongArrayElements, jenv) $target, jlp, 0);
}

XDeviceInfo*
XListInputDevices (Display* display, int * INT_OUT);

%typemap(java,jni) XDeviceInfo* {jlong} 
%typemap(java,jtype) XDeviceInfo* {long} 
%typemap(java,out) XDeviceInfo* {}


XDevice*
XOpenDevice(Display* display, XID id);

%typemap(java,jni)  XEventClass event_class {jlong} 
%typemap(java,jtype) XDeviceInfo* {long} 
%typemap(java,out) XDeviceInfo* {}

#define Relative                0
#define Absolute                1
int
XSetDeviceMode( Display* display, XDevice* device, int mode);


EventFinder*
MyProximityIn(XDevice*);

EventFinder*
MyProximityOut(XDevice*);

EventFinder*
MyDeviceMotionNotify(XDevice*);


%typemap(java,jni)  XEventClass* event_class_list {jintArray} 
%typemap(java,jtype) XEventClass* event_class_list {int[]}
%typemap(java,in) XEventClass* event_class_list {
	$target = (XEventClass*) JCALL(GetIntArrayElements, jenv) $source, 0);
}

int
XSelectExtensionEvent(Display * display, Window w, XEventClass*	event_class_list, int count);

int
myXSelectExtensionEvent(Display * display, Window w, XEventClass* event_class_list, int count);

XEvent*
newXEvent();

int
XNextEvent(Display *, XEvent *);

int
XPending(Display *);

typedef struct 
    {
    int             type;      /* ProximityIn or ProximityOut */        
    unsigned long   serial;    /* # of last request processed by server */
    Bool            send_event; /* true if this came from a SendEvent request */
    Display         *display;  /* Display the event was read from */
    Window          window;      
    XID	            deviceid;
    Window          root;            
    Window          subwindow;      
    Time            time;            
    int             x, y;            
    int             x_root, y_root;  
    unsigned int    state;           
    Bool            same_screen;     
    unsigned int    device_state; /* device key or button mask */
    unsigned char   axes_count;
    unsigned char   first_axis;
    int             axis_data[6];
    } XProximityNotifyEvent;
typedef XProximityNotifyEvent XProximityInEvent;
typedef XProximityNotifyEvent XProximityOutEvent;


typedef struct 
    {
    int           type;        /* of event */
    unsigned long serial;      /* # of last request processed by server */
    Bool          send_event;  /* true if from a SendEvent request */
    Display       *display;    /* Display the event was read from */
    Window        window;      /* "event" window reported relative to */
    XID           deviceid;
    Window        root;        /* root window that the event occured on */
    Window        subwindow;   /* child window */
    Time          time;        /* milliseconds */
    int           x, y;        /* x, y coordinates in event window */
    int           x_root;      /* coordinates relative to root */
    int           y_root;      /* coordinates relative to root */
    unsigned int  state;       /* key or button mask */
    char          is_hint;     /* detail */
    Bool          same_screen; /* same screen flag */
    unsigned int  device_state; /* device key or button mask */
    unsigned char axes_count;
    unsigned char first_axis;
    int           axis_data[6];
    } XDeviceMotionEvent;


